package panel

import (
	"encoding/json"
	"gitee.com/watertreestar/octans-device-sdk/internal"
	"strings"
)

const (
	Version = "0.2"
)

var g *internal.IDGenerator

func init() {
	generator := internal.NewIDGenerator(10000)
	g = generator
}

// 把数据转换为小钢炮可识别的数据
func decorate(jsonPayload map[string]interface{}) (int64, []byte, error) {
	gen := g.Generate()
	seq := int64(gen)
	jsonPayload["index"] = seq
	jsonPayload["version"] = Version
	b, err := json.Marshal(jsonPayload)
	return seq, b, err
}

type Input struct {
	SerialNum  string     `json:"serialno"`
	MAC        string     `json:"mac"`
	Version    string     `json:"version"`
	IPAddr     string     `json:"ipaddr"`
	Port       string     `json:"port"`
	LastResult LastResult `json:"last_result"`
}

func (i *Input) UnmarshalJSON(data []byte) error {
	type Alias Input
	t := &struct {
		MAC        string `json:"mac"`
		SerialNum  string `json:"serialno"`
		LastResult string `json:"last_result"`
		*Alias
	}{
		Alias: (*Alias)(i),
	}
	if err := json.Unmarshal(data, &t); err != nil {
		return err
	}
	i.MAC = strings.ToUpper(t.MAC)
	i.SerialNum = strings.ToUpper(t.SerialNum)
	var lr LastResult
	if err := json.Unmarshal([]byte(t.LastResult), &lr); err != nil {
		return err
	}
	i.LastResult = lr
	return nil
}

func (i *Input) isAckReply() bool {
	return i.LastResult.Index != 0
}

type LastResult struct {
	Body  map[string]interface{} `json:"body"`
	Cmd   string                 `json:"cmd"`
	Code  int                    `json:"code"`
	Index int64                  `json:"index"`
	Reply string                 `json:"reply"`
}

type AckOutput struct {
	Code     int    `json:"code"`
	Sequence int64  `json:"sequence"`
	Msg      string `json:"msg"`
}

func newSuccessAckOutput(seq int64) []byte {
	d := AckOutput{
		0,
		seq,
		"",
	}
	j, _ := json.Marshal(d)
	return j
}

// 尝试对识别结果推送数据解码
func attemptRecognise(input map[string]interface{}) (sequence int64, result RecogniseResult, err error) {
	t, ok := input["type"].(string)
	if !ok {
		return 0, RecogniseResult{}, ResultBodyInvalidError
	}
	body, ok := input["body"].(map[string]interface{})
	if !ok {
		return 0, RecogniseResult{}, ResultBodyInvalidError
	}
	seq, ok := body["sequence"].(float64)
	if !ok {
		return 0, RecogniseResult{}, ResultBodyInvalidError
	}
	sequenceNum := int64(seq)
	sn, ok := input["sn"].(string)
	if !ok {
		sn, ok = body["sn"].(string)
	}
	if !ok {
		return 0, RecogniseResult{}, ResultBodyInvalidError
	}
	var recoType RecogniseType
	switch t {
	case "face_result":
		recoType = FaceResult
	case "idcard_read":
		recoType = IDCardResult
	case "wgin_read":
		recoType = ICCardResult
	}
	var rr = RecogniseResult{
		SN:         strings.ToUpper(sn),
		ResultType: recoType,
		Content:    body,
	}
	return sequenceNum, rr, nil
}
